package com.portal.utils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;

public final class GeradorDeExcel {

	private Workbook workbookAtual;

	private Sheet sheetAtual;
	private int cursorLinhaAtual = 0;
	private int cursorColunaAtual = 0;

	public GeradorDeExcel(){

	}

	public Excel carregarExcel(InputStream arquivoStream) throws IOException{
		try {
			workbookAtual = WorkbookFactory.create(arquivoStream);
		} catch (InvalidFormatException e) {
			e.printStackTrace();
		}
		return new Excel();
	}

	public ByteArrayOutputStream salvarExcel() throws IOException{
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		workbookAtual.write(baos);
		return baos;
	}

	public class Excel {		
		public Planilha abrirPlanilhaNumero(int numeroDaPlanilha){
			sheetAtual = workbookAtual.getSheetAt(numeroDaPlanilha);
			return new Planilha(0, 0);
		}
	}

	public class Planilha {
		public Planilha(int linha, int coluna){
			cursorLinhaAtual = linha;
			cursorColunaAtual = coluna;
		}

		public Planilha abrirPlanilhaNumero(int numeroDaPlanilha){
			sheetAtual = workbookAtual.getSheetAt(numeroDaPlanilha);
			return new Planilha(0, 0);
		}

		public Planilha selecionarLinhaNumero(int linha){
			cursorLinhaAtual = linha;
			return this;
		}

		public Planilha selecionarColunaNumero(int coluna){
			cursorColunaAtual = coluna;
			return this;
		}

		public Planilha preencherCabecalhoCom(String[] dadosCabecalho){
			int linha = cursorLinhaAtual;
			int coluna = cursorColunaAtual;
			Row linhaDoCabecalho = extrairLinha(sheetAtual, linha);
			for(String nome : dadosCabecalho){
				preencherCelula(linhaDoCabecalho, coluna, nome);
				coluna++;
			}
			redimensionarLarguraDasColunas(0, coluna - 1);
			return this;
		}

		public Planilha preencherLinhasCom(List<Object[]> dadosDasLinhas){
			int linha = cursorLinhaAtual;
			int colunaFinal = 0;
			for(Object[] dadosDaLinha : dadosDasLinhas){
				Row linhaAtual = extrairLinha(sheetAtual, linha);
				int coluna = cursorColunaAtual;
				for(Object dadoDaColuna : dadosDaLinha){
					preencherCelula(linhaAtual, coluna, dadoDaColuna);
					coluna++;
				}
				linha++;
				colunaFinal = coluna;
			}
			redimensionarLarguraDasColunas(0, colunaFinal - 1);
			return this;
		}

		public Planilha preencherCelulaCom(Object dadoDaCelula){
			Row linhaAtual = extrairLinha(sheetAtual, cursorLinhaAtual);
			preencherCelula(linhaAtual, cursorColunaAtual, dadoDaCelula);
			redimensionarLarguraDasColunas(cursorColunaAtual, cursorColunaAtual);
			return this;
		}

		private void preencherCelula(Row row, Integer coluna, Object dado) {
			Cell celula = extrairCelula(row, coluna);
			if (dado instanceof Integer){
				celula.setCellValue((Integer)dado);
			} else if (dado instanceof Double){
				celula.setCellValue((Double)dado);
			} else if (dado instanceof Calendar){
				celula.setCellValue((Calendar)dado);
			} else if (dado instanceof Date){
				celula.setCellValue((Date)dado);
			} else
				celula.setCellValue(dado.toString());
		}

		private Row extrairLinha(Sheet sheet, Integer numLinha) {
			Row linha = sheet.getRow(numLinha);
			if(linha == null){
				linha = sheet.createRow(numLinha);
			}
			return linha;
		}

		private Cell extrairCelula(Row row, Integer coluna) {
			Cell celula = row.getCell(coluna);
			if(celula == null){
				celula = row.createCell(coluna);
			}
			return celula;
		}

		private void redimensionarLarguraDasColunas(Integer linhaInicial, Integer linhaFinal){
			for(int i = linhaInicial ; i <= linhaFinal ; i++){
				sheetAtual.autoSizeColumn(i);
			}
		}
	}
}